﻿<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SpringCloud(16) 整合Seata+多数据源+sharding-jdbc</title>
  <link rel="stylesheet" href="https://stackedit.io/style.css" />
</head>

<body class="stackedit">
  <div class="stackedit__html"><p></p><div class="toc"><h3>文章目录</h3><ul><ul><ul><li><a href="#_3">一、前言</a></li><li><a href="#dockercomposeSeata_14">二、docker-compose一键部署Seata</a></li><li><a href="#_18">三、项目整合</a></li><ul><li><a href="#1_22">1、引入依赖</a></li><li><a href="#2_63">2、增加配置文件</a></li><li><a href="#3_227">3、数据源配置</a></li><li><a href="#4resourcesseataconf_319">4、各个微服务下的resources目录下准备`seata.conf`</a></li></ul><li><a href="#_330">四、编写业务代码进行测试</a></li><ul><li><a href="#1_334">1、分库分表</a></li><ul><li><a href="#a_336">a:父服务声明（主业务调用方）</a></li><li><a href="#b_343">b:子服务声明</a></li></ul><li><a href="#2_350">2、多数据源</a></li></ul><li><a href="#Demo_359">五、源码案例Demo</a></li></ul></ul></ul></div><p></p>
<h3><a id="_3"></a>一、前言</h3>
<p>本文通过以下环境整合<code>Seata</code> + <code>多数据源</code> + <code>sharding-jdbc</code></p>
<ol>
<li>spring-boot 2.7.0</li>
<li>spring-cloud 2021.0.2</li>
<li>spring-cloud-alibaba 2021.0.1.0</li>
<li>sharding-jdbc 4.1.1</li>
<li>seata-server 1.5.2</li>
<li>dynamic-datasource 3.3.2</li>
</ol>
<h3><a id="dockercomposeSeata_14"></a>二、docker-compose一键部署Seata</h3>
<p>见 <a href="https://gitee.com/zhengqingya/docker-compose">https://gitee.com/zhengqingya/docker-compose</a></p>
<h3><a id="_18"></a>三、项目整合</h3>
<blockquote>
<p>tips: 详情见文末提供的源码demo</p>
</blockquote>
<h4><a id="1_22"></a>1、引入依赖</h4>
<pre><code class="prism language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- sharding-jdbc --&gt;</span>
    <span class="token comment">&lt;!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-spring-boot-starter --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.shardingsphere<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>sharding-jdbc-spring-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>4.1.1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- 整合seata --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.shardingsphere<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>sharding-transaction-base-seata-at<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>4.1.1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- 动态数据源 --&gt;</span>
    <span class="token comment">&lt;!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.baomidou<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>dynamic-datasource-spring-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>3.3.2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- seata --&gt;</span>
    <span class="token comment">&lt;!-- 最外层父pom.xml中统一管理seata版本 （全局修改版本为1.5.2） --&gt;</span>
    <span class="token comment">&lt;!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-seata --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>spring-cloud-starter-alibaba-seata<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- https://mvnrepository.com/artifact/io.seata/seata-spring-boot-starter --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>io.seata<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>seata-spring-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">&gt;</span></span>
</code></pre>
<h4><a id="2_63"></a>2、增加配置文件</h4>
<pre><code class="prism language-yml"><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token comment"># 多数据源配置 可参考 https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter</span>
  <span class="token key atrule">datasource</span><span class="token punctuation">:</span>
    <span class="token key atrule">type</span><span class="token punctuation">:</span> com.alibaba.druid.pool.DruidDataSource
    <span class="token key atrule">dynamic</span><span class="token punctuation">:</span>
      <span class="token key atrule">primary</span><span class="token punctuation">:</span> master <span class="token comment"># 设置默认的数据源或者数据源组,默认值即为master</span>
      <span class="token key atrule">strict</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>   <span class="token comment"># 设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.</span>
      <span class="token key atrule">datasource</span><span class="token punctuation">:</span>
        <span class="token key atrule">master</span><span class="token punctuation">:</span>
          <span class="token key atrule">url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/demo<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
          <span class="token key atrule">username</span><span class="token punctuation">:</span> root
          <span class="token key atrule">password</span><span class="token punctuation">:</span> root
          <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">db-test</span><span class="token punctuation">:</span>
          <span class="token key atrule">url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/demo<span class="token punctuation">-</span>bak<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
          <span class="token key atrule">username</span><span class="token punctuation">:</span> root
          <span class="token key atrule">password</span><span class="token punctuation">:</span> root
          <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver

      <span class="token comment"># 开启seata代理，开启后默认每个数据源都代理，如果某个不需要代理可单独关闭</span>
      <span class="token key atrule">seata</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
      <span class="token key atrule">seata-mode</span><span class="token punctuation">:</span> at


  <span class="token comment"># sharding-jdbc配置</span>
  <span class="token key atrule">shardingsphere</span><span class="token punctuation">:</span>
    <span class="token comment"># 是否开启SQL显示</span>
    <span class="token key atrule">props</span><span class="token punctuation">:</span>
      <span class="token key atrule">sql</span><span class="token punctuation">:</span>
        <span class="token key atrule">show</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>
    <span class="token comment"># ====================== ↓↓↓↓↓↓ 数据源配置 ↓↓↓↓↓↓ ======================</span>
    <span class="token key atrule">datasource</span><span class="token punctuation">:</span>
      <span class="token key atrule">names</span><span class="token punctuation">:</span> ds<span class="token punctuation">-</span>master<span class="token punctuation">-</span><span class="token number">0</span><span class="token punctuation">,</span>ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>0<span class="token punctuation">-</span><span class="token number">1</span><span class="token punctuation">,</span>ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>0<span class="token punctuation">-</span><span class="token number">2</span><span class="token punctuation">,</span>ds<span class="token punctuation">-</span>master<span class="token punctuation">-</span><span class="token number">1</span><span class="token punctuation">,</span>ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>1<span class="token punctuation">-</span><span class="token number">1</span><span class="token punctuation">,</span>ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>1<span class="token punctuation">-</span><span class="token number">2</span>
      <span class="token comment"># ====================== ↓↓↓↓↓↓ 配置第1个主从库 ↓↓↓↓↓↓ ======================</span>
      <span class="token comment"># 主库1</span>
      <span class="token key atrule">ds-master-0</span><span class="token punctuation">:</span>
        <span class="token key atrule">type</span><span class="token punctuation">:</span> com.zaxxer.hikari.HikariDataSource
        <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">jdbc-url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/ds0<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
        <span class="token key atrule">username</span><span class="token punctuation">:</span> root
        <span class="token key atrule">password</span><span class="token punctuation">:</span> root
      <span class="token comment"># 主库1-从库1</span>
      <span class="token key atrule">ds-slave-0-1</span><span class="token punctuation">:</span>
        <span class="token key atrule">type</span><span class="token punctuation">:</span> com.zaxxer.hikari.HikariDataSource
        <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">jdbc-url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/ds0<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
        <span class="token key atrule">username</span><span class="token punctuation">:</span> root
        <span class="token key atrule">password</span><span class="token punctuation">:</span> root
      <span class="token comment"># 主库1-从库2</span>
      <span class="token key atrule">ds-slave-0-2</span><span class="token punctuation">:</span>
        <span class="token key atrule">type</span><span class="token punctuation">:</span> com.zaxxer.hikari.HikariDataSource
        <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">jdbc-url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/ds0<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
        <span class="token key atrule">username</span><span class="token punctuation">:</span> root
        <span class="token key atrule">password</span><span class="token punctuation">:</span> root
      <span class="token comment"># ====================== ↓↓↓↓↓↓ 配置第2个主从库 ↓↓↓↓↓↓ ======================</span>
      <span class="token comment"># 主库2</span>
      <span class="token key atrule">ds-master-1</span><span class="token punctuation">:</span>
        <span class="token key atrule">type</span><span class="token punctuation">:</span> com.zaxxer.hikari.HikariDataSource
        <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">jdbc-url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/ds1<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
        <span class="token key atrule">username</span><span class="token punctuation">:</span> root
        <span class="token key atrule">password</span><span class="token punctuation">:</span> root
      <span class="token comment"># 主库2-从库1</span>
      <span class="token key atrule">ds-slave-1-1</span><span class="token punctuation">:</span>
        <span class="token key atrule">type</span><span class="token punctuation">:</span> com.zaxxer.hikari.HikariDataSource
        <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">jdbc-url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/ds1<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
        <span class="token key atrule">username</span><span class="token punctuation">:</span> root
        <span class="token key atrule">password</span><span class="token punctuation">:</span> root
      <span class="token comment"># 主库2-从库2</span>
      <span class="token key atrule">ds-slave-1-2</span><span class="token punctuation">:</span>
        <span class="token key atrule">type</span><span class="token punctuation">:</span> com.zaxxer.hikari.HikariDataSource
        <span class="token key atrule">driver-class-name</span><span class="token punctuation">:</span> com.mysql.cj.jdbc.Driver
        <span class="token key atrule">jdbc-url</span><span class="token punctuation">:</span> jdbc<span class="token punctuation">:</span>mysql<span class="token punctuation">:</span>//127.0.0.1<span class="token punctuation">:</span>3306/ds1<span class="token punctuation">?</span>allowMultiQueries=true<span class="token important">&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</span> <span class="token comment"># MySQL在高版本需要指明是否进行SSL连接 解决则加上 &amp;useSSL=false</span>
        <span class="token key atrule">username</span><span class="token punctuation">:</span> root
        <span class="token key atrule">password</span><span class="token punctuation">:</span> root

    <span class="token key atrule">sharding</span><span class="token punctuation">:</span>
      <span class="token comment"># ====================== ↓↓↓↓↓↓ 读写分离配置 ↓↓↓↓↓↓ ======================</span>
      <span class="token key atrule">master-slave-rules</span><span class="token punctuation">:</span>
        <span class="token key atrule">ds-master-0</span><span class="token punctuation">:</span>
          <span class="token comment"># 主库</span>
          <span class="token key atrule">masterDataSourceName</span><span class="token punctuation">:</span> ds<span class="token punctuation">-</span>master<span class="token punctuation">-</span><span class="token number">0</span>
          <span class="token comment"># 从库</span>
          <span class="token key atrule">slaveDataSourceNames</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>0<span class="token punctuation">-</span><span class="token number">1</span>
            <span class="token punctuation">-</span> ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>0<span class="token punctuation">-</span><span class="token number">2</span>
          <span class="token comment"># 从库查询数据的负载均衡算法 目前有2种算法 round_robin（轮询）和 random（随机）</span>
          <span class="token comment"># 算法接口 org.apache.shardingsphere.spi.masterslave.MasterSlaveLoadBalanceAlgorithm</span>
          <span class="token comment"># 实现类 RandomMasterSlaveLoadBalanceAlgorithm 和 RoundRobinMasterSlaveLoadBalanceAlgorithm</span>
          <span class="token key atrule">loadBalanceAlgorithmType</span><span class="token punctuation">:</span> ROUND_ROBIN
        <span class="token key atrule">ds-master-1</span><span class="token punctuation">:</span>
          <span class="token key atrule">masterDataSourceName</span><span class="token punctuation">:</span> ds<span class="token punctuation">-</span>master<span class="token punctuation">-</span><span class="token number">1</span>
          <span class="token key atrule">slaveDataSourceNames</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>1<span class="token punctuation">-</span><span class="token number">1</span>
            <span class="token punctuation">-</span> ds<span class="token punctuation">-</span>slave<span class="token punctuation">-</span>1<span class="token punctuation">-</span><span class="token number">2</span>
          <span class="token key atrule">loadBalanceAlgorithmType</span><span class="token punctuation">:</span> ROUND_ROBIN

      <span class="token comment"># ====================== ↓↓↓↓↓↓ 分库分表配置 ↓↓↓↓↓↓ ======================</span>
      <span class="token key atrule">tables</span><span class="token punctuation">:</span>
        <span class="token key atrule">t_user</span><span class="token punctuation">:</span>
          <span class="token key atrule">actual-data-nodes</span><span class="token punctuation">:</span> ds<span class="token punctuation">-</span>master<span class="token punctuation">-</span>$<span class="token punctuation">-</span><span class="token punctuation">&gt;</span><span class="token punctuation">{</span>0..1<span class="token punctuation">}</span>.t_user$<span class="token punctuation">-</span><span class="token punctuation">&gt;</span><span class="token punctuation">{</span>0..1<span class="token punctuation">}</span>
          <span class="token key atrule">database-strategy</span><span class="token punctuation">:</span>
            <span class="token key atrule">complex</span><span class="token punctuation">:</span>
              <span class="token key atrule">sharding-columns</span><span class="token punctuation">:</span> create_time
              <span class="token key atrule">algorithm-class-name</span><span class="token punctuation">:</span> com.zhengqing.common.db.config.sharding.user.complex.MyDbComplexKeysShardingAlgorithm
          <span class="token key atrule">table-strategy</span><span class="token punctuation">:</span>
            <span class="token key atrule">complex</span><span class="token punctuation">:</span>
              <span class="token key atrule">sharding-columns</span><span class="token punctuation">:</span> user_id
              <span class="token key atrule">algorithm-class-name</span><span class="token punctuation">:</span> com.zhengqing.common.db.config.sharding.user.complex.MyTableComplexKeysShardingAlgorithm
        <span class="token key atrule">t_order</span><span class="token punctuation">:</span>
          <span class="token key atrule">actual-data-nodes</span><span class="token punctuation">:</span> ds<span class="token punctuation">-</span>master<span class="token punctuation">-</span>$<span class="token punctuation">-</span><span class="token punctuation">&gt;</span><span class="token punctuation">{</span>0..1<span class="token punctuation">}</span>.t_order$<span class="token punctuation">-</span><span class="token punctuation">&gt;</span><span class="token punctuation">{</span>0..1<span class="token punctuation">}</span>
          <span class="token key atrule">database-strategy</span><span class="token punctuation">:</span>
            <span class="token key atrule">complex</span><span class="token punctuation">:</span>
              <span class="token key atrule">sharding-columns</span><span class="token punctuation">:</span> pay_time
              <span class="token key atrule">algorithm-class-name</span><span class="token punctuation">:</span> com.zhengqing.common.db.config.sharding.order.complex.MyDbComplexKeysShardingAlgorithm
          <span class="token key atrule">table-strategy</span><span class="token punctuation">:</span>
            <span class="token key atrule">complex</span><span class="token punctuation">:</span>
              <span class="token key atrule">sharding-columns</span><span class="token punctuation">:</span> user_id
              <span class="token key atrule">algorithm-class-name</span><span class="token punctuation">:</span> com.zhengqing.common.db.config.sharding.order.complex.MyTableComplexKeysShardingAlgorithm

<span class="token comment"># seata配置</span>
<span class="token key atrule">seata</span><span class="token punctuation">:</span>
  <span class="token comment"># 是否开启seata</span>
  <span class="token key atrule">enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
  <span class="token comment"># Seata 应用编号，默认为 ${spring.application.name}</span>
  <span class="token key atrule">application-id</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.application.name<span class="token punctuation">}</span>
  <span class="token comment"># Seata 事务组编号，用于 TC 集群名</span>
  <span class="token key atrule">tx-service-group</span><span class="token punctuation">:</span> test<span class="token punctuation">-</span>tx<span class="token punctuation">-</span>group
  <span class="token comment"># 是否开启数据源代理</span>
  <span class="token key atrule">enable-auto-data-source-proxy</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>
  <span class="token key atrule">data-source-proxy-mode</span><span class="token punctuation">:</span> AT
  <span class="token comment"># 服务配置项</span>
  <span class="token key atrule">service</span><span class="token punctuation">:</span>
    <span class="token comment"># 虚拟组和分组的映射</span>
    <span class="token key atrule">vgroup-mapping</span><span class="token punctuation">:</span>
      <span class="token key atrule">test-tx-group</span><span class="token punctuation">:</span> default
    <span class="token comment"># 分组和 Seata 服务的映射</span>
    <span class="token key atrule">grouplist</span><span class="token punctuation">:</span>
      <span class="token key atrule">default</span><span class="token punctuation">:</span> 127.0.0.1<span class="token punctuation">:</span><span class="token number">8091</span>
  <span class="token key atrule">config</span><span class="token punctuation">:</span>
    <span class="token key atrule">type</span><span class="token punctuation">:</span> nacos
    <span class="token key atrule">nacos</span><span class="token punctuation">:</span>
      <span class="token key atrule">serverAddr</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.server<span class="token punctuation">-</span>addr<span class="token punctuation">}</span>
      <span class="token key atrule">group</span><span class="token punctuation">:</span> SEATA_GROUP
      <span class="token key atrule">namespace</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.namespace<span class="token punctuation">}</span>
      <span class="token key atrule">username</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.username<span class="token punctuation">}</span>
      <span class="token key atrule">password</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.password<span class="token punctuation">}</span>
      <span class="token key atrule">dataId</span><span class="token punctuation">:</span> seata<span class="token punctuation">-</span>server.properties
  <span class="token key atrule">registry</span><span class="token punctuation">:</span>
    <span class="token key atrule">type</span><span class="token punctuation">:</span> nacos
    <span class="token key atrule">nacos</span><span class="token punctuation">:</span>
      <span class="token key atrule">application</span><span class="token punctuation">:</span> seata<span class="token punctuation">-</span>server
      <span class="token key atrule">server-addr</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.server<span class="token punctuation">-</span>addr<span class="token punctuation">}</span>
      <span class="token key atrule">group</span><span class="token punctuation">:</span> SEATA_GROUP
      <span class="token key atrule">namespace</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.namespace<span class="token punctuation">}</span>
      <span class="token key atrule">username</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.username<span class="token punctuation">}</span>
      <span class="token key atrule">password</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>spring.cloud.nacos.config.password<span class="token punctuation">}</span>
</code></pre>
<h4><a id="3_227"></a>3、数据源配置</h4>
<pre><code class="prism language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>zhengqing<span class="token punctuation">.</span>common<span class="token punctuation">.</span>db<span class="token punctuation">.</span>config<span class="token punctuation">.</span>dynamic</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>dynamic<span class="token punctuation">.</span>datasource<span class="token punctuation">.</span></span><span class="token class-name">DynamicRoutingDataSource</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>dynamic<span class="token punctuation">.</span>datasource<span class="token punctuation">.</span>provider<span class="token punctuation">.</span></span><span class="token class-name">AbstractDataSourceProvider</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>dynamic<span class="token punctuation">.</span>datasource<span class="token punctuation">.</span>provider<span class="token punctuation">.</span></span><span class="token class-name">DynamicDataSourceProvider</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>dynamic<span class="token punctuation">.</span>datasource<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">DataSourceProperty</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>dynamic<span class="token punctuation">.</span>datasource<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">DynamicDataSourceAutoConfiguration</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">com<span class="token punctuation">.</span>baomidou<span class="token punctuation">.</span>dynamic<span class="token punctuation">.</span>datasource<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">DynamicDataSourceProperties</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>shardingsphere<span class="token punctuation">.</span>shardingjdbc<span class="token punctuation">.</span>jdbc<span class="token punctuation">.</span>adapter<span class="token punctuation">.</span></span><span class="token class-name">AbstractDataSourceAdapter</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>beans<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Autowired</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span></span><span class="token class-name">SpringBootConfiguration</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">AutoConfigureBefore</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Bean</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Configuration</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Lazy</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Primary</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token namespace">javax<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Resource</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">javax<span class="token punctuation">.</span>sql<span class="token punctuation">.</span></span><span class="token class-name">DataSource</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Map</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * &lt;p&gt; sharding-jdbc集成动态数据源配置 &lt;/p&gt;
 *
 * @author zhengqingya
 * @description 使用 {@link com.baomidou.dynamic.datasource.annotation.DS} 注解，切换数据源
 * ex: 切换为sharding-jdbc数据源 =&gt; @DS(DataSourceConfig.SHARDING_DATA_SOURCE_NAME)
 * @date 2021/11/2 10:13
 */</span>
<span class="token annotation punctuation">@Configuration</span>
<span class="token annotation punctuation">@AutoConfigureBefore</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token class-name">DynamicDataSourceAutoConfiguration</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token class-name">SpringBootConfiguration</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DataSourceConfig</span> <span class="token punctuation">{</span>
    <span class="token comment">/**
     * 分表数据源名称
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> SHARDING_DATA_SOURCE_NAME <span class="token operator">=</span> <span class="token string">"sharding-data-source"</span><span class="token punctuation">;</span>
    <span class="token comment">/**
     * 动态数据源配置项
     */</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">DynamicDataSourceProperties</span> properties<span class="token punctuation">;</span>

    <span class="token comment">/**
     * sharding-jdbc有四种数据源，需要根据业务注入不同的数据源
     * &lt;p&gt;
     * 1.未使用分片, 脱敏的名称(默认): shardingDataSource;
     * 2.主从数据源: masterSlaveDataSource;
     * 3.脱敏数据源：encryptDataSource;
     * 4.影子数据源：shadowDataSource
     */</span>
    <span class="token annotation punctuation">@Lazy</span>
    <span class="token annotation punctuation">@Resource</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">"shardingDataSource"</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">AbstractDataSourceAdapter</span> shardingDataSource<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">DynamicDataSourceProvider</span> <span class="token function">dynamicDataSourceProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">DataSourceProperty</span><span class="token punctuation">&gt;</span></span> datasourceMap <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>properties<span class="token punctuation">.</span><span class="token function">getDatasource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">AbstractDataSourceProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token annotation punctuation">@Override</span>
            <span class="token keyword">public</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">DataSource</span><span class="token punctuation">&gt;</span></span> <span class="token function">loadDataSources</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">DataSource</span><span class="token punctuation">&gt;</span></span> dataSourceMap <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">createDataSourceMap</span><span class="token punctuation">(</span>datasourceMap<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">// 将 shardingjdbc 管理的数据源也交给动态数据源管理</span>
                dataSourceMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>SHARDING_DATA_SOURCE_NAME<span class="token punctuation">,</span> <span class="token class-name">DataSourceConfig</span><span class="token punctuation">.</span><span class="token keyword">this</span><span class="token punctuation">.</span>shardingDataSource<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">return</span> dataSourceMap<span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 将动态数据源设置为首选的
     * 当spring存在多个数据源时, 自动注入的是首选的对象
     * 设置为主要的数据源之后，就可以支持sharding-jdbc原生的配置方式了
     */</span>
    <span class="token annotation punctuation">@Primary</span>
    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">DataSource</span> <span class="token function">dataSource</span><span class="token punctuation">(</span><span class="token class-name">DynamicDataSourceProvider</span> dynamicDataSourceProvider<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">DynamicRoutingDataSource</span> dataSource <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DynamicRoutingDataSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        dataSource<span class="token punctuation">.</span><span class="token function">setPrimary</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>properties<span class="token punctuation">.</span><span class="token function">getPrimary</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        dataSource<span class="token punctuation">.</span><span class="token function">setStrict</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>properties<span class="token punctuation">.</span><span class="token function">getStrict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        dataSource<span class="token punctuation">.</span><span class="token function">setStrategy</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>properties<span class="token punctuation">.</span><span class="token function">getStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        dataSource<span class="token punctuation">.</span><span class="token function">setProvider</span><span class="token punctuation">(</span>dynamicDataSourceProvider<span class="token punctuation">)</span><span class="token punctuation">;</span>
        dataSource<span class="token punctuation">.</span><span class="token function">setP6spy</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>properties<span class="token punctuation">.</span><span class="token function">getP6spy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        dataSource<span class="token punctuation">.</span><span class="token function">setSeata</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>properties<span class="token punctuation">.</span><span class="token function">getSeata</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> dataSource<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre>
<h4><a id="4resourcesseataconf_319"></a>4、各个微服务下的resources目录下准备<code>seata.conf</code></h4>
<p>eg:</p>
<pre><code>client {
    application.id = user-server
    transaction.service.group = test-tx-group
}
</code></pre>
<h3><a id="_330"></a>四、编写业务代码进行测试</h3>
<blockquote>
<p>使用：在对应的业务方法上加上相应的注解即可…</p>
</blockquote>
<h4><a id="1_334"></a>1、分库分表</h4>
<h5><a id="a_336"></a>a:父服务声明（主业务调用方）</h5>
<pre><code>@GlobalTransactional(rollbackFor = Exception.class)
@ShardingTransactionType(TransactionType.BASE)
</code></pre>
<h5><a id="b_343"></a>b:子服务声明</h5>
<pre><code>@Transactional(rollbackFor = Exception.class)
@ShardingTransactionType(TransactionType.BASE)
</code></pre>
<h4><a id="2_350"></a>2、多数据源</h4>
<p>单库单表</p>
<pre><code>@GlobalTransactional(rollbackFor = Exception.class)
@DS("db-test")
</code></pre>
<h3><a id="Demo_359"></a>五、源码案例Demo</h3>
<p><a href="https://gitee.com/zhengqingya/java-workspace">https://gitee.com/zhengqingya/java-workspace</a></p>
<hr>
<blockquote>
<p>今日分享语句：<br>
耐心和恒心是学习的良药，坚持不懈是成功的关键。</p>
</blockquote>
</div>
</body>

</html>
